######################################################################
# File: server/ma...nt/co...ds/runmudserver.py     Part of DjangoMUD #
#                                                                    #
# Copyright (C) 2010, Joachim Pileborg.                              #
# All rights reserved.                                               #
#                                                                    #
# Redistribution and use in source and binary forms, with or without #
# modification, are permitted provided that the following conditions #
# are met:                                                           #
#                                                                    #
#   o Redistributions of source code must retain the above copyright #
#     notice, this list of conditions and the following disclaimer.  #
#   o Redistributions in binary form must reproduce the above        #
#     copyright notice, this list of conditions and the following    #
#     disclaimer in the documentation and/or other materials         #
#     provided with the distribution.                                #
#   o Neither the name of the author nor the names of its            #
#     contributors may be used to endorse or promote products        #
#     derived from this software without specific prior written      #
#     permission.                                                    #
#                                                                    #
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND             #
# CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,        #
# INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF           #
# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE           #
# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS  #
# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,#
# OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,           #
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR #
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY       #
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR     #
# TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF #
# THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF    #
# SUCH DAMAGE.                                                       #
######################################################################

from optparse import make_option
import threading

from django.conf import settings

__all__ = [ 'Command' ]

from djangomud.server.management.djangomudbasecommand import DjangoMUDBaseCommand

######################################################################

# TODO
# ====
# o I just realized that using processes will not work! One reason I
#   want to use Django is because I could easily make a web-portal for
#   the MUD, but if different parts are in different processes, it
#   might be hard to share data between those processes!
#   It seems like I have to start experimenting with threads again!
#   *Sigh*

######################################################################

class Command(DjangoMUDBaseCommand):
    """
    Custom command to run both the MUD server, and Djangos built-in
    web server for a web portal.
    """
    option_list = DjangoMUDBaseCommand.option_list + (
        make_option('--telnetport', action='store', dest='telnet_port',
                    default=settings.DEFAULT_TELNET_PORT,
                    help='Tells Django the portnumber for telnet connections.'),
        make_option('--telnetaddr', action='store', dest='telnet_addr',
                    default=settings.DEFAULT_TELNET_ADDR,
                    help='Tells Django the address to bind to for telnet connections.'),
        make_option('--httpport', action='store', dest='http_port',
                    default=settings.DEFAULT_HTTP_PORT,
                    help='Tells Django the portnumber for web connections.'),
        make_option('--httpaddr', action='store', dest='http_addr',
                    default=settings.DEFAULT_HTTP_ADDR,
                    help='Tells Django the address to bind to for web connections.'),
        make_option('--adminmedia', dest='admin_media_path', default='',
                    help='Specifies the directory from which to serve admin media.'),
        )

    help = "Start both the normal MUD server, and also a web-server for administration."

    # Validation is called explicitly each time the server is reloaded.
    requires_model_validation = False

    class BaseRunServer(threading.Thread):
        options = None
        server = None

        def __init__(self, options):
            super(Command.BaseRunServer, self).__init__()
            self.options = options

        def setup(self):
            pass

        def run(self):
            self.setup()
            if self.server is not None:
                self.server.run()

    class RunMUDServer(BaseRunServer):
        def setup(self):
            from djangomud.server.mudserver import MUDServer

            self.server = MUDServer()
            self.server.telnet_addr = self.options.get('telnet_addr', settings.DEFAULT_TELNET_ADDR)
            self.server.telnet_port = self.options.get('telnet_port', settings.DEFAULT_TELNET_PORT)

    class RunWebServer(BaseRunServer):
        def setup(self):
            from djangomud.server.webserver import WebServer

            self.server = WebServer()
            self.server.web_addr = self.options.get('http_addr', settings.DEFAULT_HTTP_ADDR)
            self.server.web_port = self.options.get('http_port', settings.DEFAULT_HTTP_PORT)
            self.server.admin_media_path =  self.options.get('admin_media_path', '')

    mud_thread = None
    web_thread = None

    def run(self, *args, **options):
        self.mud_thread = Command.RunMUDServer(options)
        self.web_thread = Command.RunWebServer(options)

        self.mud_thread.start()
        self.web_thread.start()

        from djangomud.server.shutdown import shutdown_event, shutdown
        while not shutdown_event.is_set():
            shutdown_event.wait(0.2)

        self.web_thread.join()
        self.mud_thread.join()

######################################################################
